home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / bin / glsa-check < prev    next >
Text File  |  2006-05-08  |  9KB  |  266 lines

  1. #!/usr/bin/python
  2.  
  3. # $Header$
  4. # This program is licensed under the GPL, version 2
  5.  
  6. import os,string,sys
  7. sys.path.insert(0, "/usr/lib/gentoolkit/pym")
  8. sys.path.insert(0, "/usr/lib/portage/pym")
  9. from output import *
  10. from getopt import getopt,GetoptError
  11.  
  12. __program__ = "glsa-check"
  13. __author__ = "Marius Mauch <genone@gentoo.org>"
  14. __version__ = "0.6"
  15.  
  16. optionmap = [
  17. ["-l", "--list", "list all unapplied GLSA"],
  18. ["-d", "--dump", "--print", "show all information about the given GLSA"],
  19. ["-t", "--test", "test if this system is affected by the given GLSA"],
  20. ["-p", "--pretend", "show the necessary commands to apply this GLSA"],
  21. ["-f", "--fix", "try to auto-apply this GLSA (experimental)"],
  22. ["-i", "--inject", "inject the given GLSA into the checkfile"],
  23. ["-n", "--nocolor", "disable colors (option)"],
  24. ["-h", "--help", "show this help message"],
  25. ["-V", "--version", "some information about this tool"],
  26. ["-v", "--verbose", "print more information (option)"],
  27. ["-c", "--cve", "show CAN ids in listing mode (option)"],
  28. ]
  29.  
  30. # print a warning as this is beta code (but proven by now, so no more warning)
  31. #sys.stderr.write("WARNING: This tool is completely new and not very tested, so it should not be\n")
  32. #sys.stderr.write("used on production systems. It's mainly a test tool for the new GLSA release\n")
  33. #sys.stderr.write("and distribution system, it's functionality will later be merged into emerge\n")
  34. #sys.stderr.write("and equery.\n")
  35. #sys.stderr.write("Please read http://www.gentoo.org/proj/en/portage/glsa-integration.xml\n")
  36. #sys.stderr.write("before using this tool AND before reporting a bug.\n\n")
  37.  
  38. # option parsing
  39. args = []
  40. params = []
  41. try:
  42.     args, params = getopt(sys.argv[1:], "dplfchinvVtc", \
  43.         ["dump", "print", "list", "pretend", "fix", "inject", "help", "info", "version", "test", "nocolor", "cve"])
  44.     args = [a for a,b in args]
  45.     
  46.     for option in ["--nocolor", "-n"]:
  47.         if option in args:
  48.             nocolor()
  49.             args.remove(option)
  50.             
  51.     verbose = False
  52.     for option in ["--verbose", "-v"]:
  53.         if option in args:
  54.             verbose = True
  55.             args.remove(option)
  56.  
  57.     list_cve = False
  58.     for option in ["--cve", "-c"]:
  59.         if option in args:
  60.             list_cve = True
  61.             args.remove(option)
  62.  
  63.     # sanity checking
  64.     if len(args) <= 0:
  65.         sys.stderr.write("no option given: what should I do ?\n")
  66.         mode="help"
  67.     elif len(args) > 1:
  68.         sys.stderr.write("please use only one command per call\n")
  69.         mode = "help"
  70.     else:
  71.         # in what mode are we ?
  72.         args = args[0]
  73.         for m in optionmap:
  74.             if args in [o for o in m[:-1]]:
  75.                 mode = m[1][2:]
  76.  
  77. except GetoptError, e:
  78.     sys.stderr.write("unknown option given: ")
  79.     sys.stderr.write(str(e)+"\n")
  80.     mode = "help"
  81.  
  82. # we need a set of glsa for most operation modes
  83. if len(params) <= 0 and mode in ["fix", "test", "pretend", "dump", "inject"]:
  84.     sys.stderr.write("\nno GLSA given, so we'll do nothing for now. \n")
  85.     sys.stderr.write("If you want to run on all GLSA please tell me so \n")
  86.     sys.stderr.write("(specify \"all\" as parameter)\n\n")
  87.     mode = "help"
  88. elif len(params) <= 0 and mode == "list":
  89.     params.append("new")
  90.     
  91. # show help message
  92. if mode == "help":
  93.     sys.stderr.write("\nSyntax: glsa-check <option> [glsa-list]\n\n")
  94.     for m in optionmap:
  95.         sys.stderr.write(m[0] + "\t" + m[1] + "   \t: " + m[-1] + "\n")
  96.         for o in m[2:-1]:
  97.             sys.stderr.write("\t" + o + "\n")
  98.     sys.stderr.write("\nglsa-list can contain an arbitrary number of GLSA ids, \n")
  99.     sys.stderr.write("filenames containing GLSAs or the special identifiers \n")
  100.     sys.stderr.write("'all', 'new' and 'affected'\n")
  101.     sys.exit(1)
  102.  
  103. # we need root priviledges for write access
  104. if mode in ["fix", "inject"] and os.geteuid() != 0:
  105.     sys.stderr.write("\nThis tool needs root access to "+mode+" this GLSA\n\n")
  106.     sys.exit(2)
  107.  
  108. # show version and copyright information
  109. if mode == "version":
  110.     sys.stderr.write("\n"+ __program__ + ", version " + __version__ + "\n")
  111.     sys.stderr.write("Author: " + __author__ + "\n")
  112.     sys.stderr.write("This program is licensed under the GPL, version 2\n\n")
  113.     sys.exit(0)
  114.  
  115. # delay this for speed increase
  116. from glsa import *
  117.  
  118. glsaconfig = checkconfig(portage.config(clone=portage.settings))
  119.  
  120. # Check that we really have a glsa dir to work on
  121. if not (os.path.exists(glsaconfig["GLSA_DIR"]) and os.path.isdir(glsaconfig["GLSA_DIR"])):
  122.     sys.stderr.write(red("ERROR")+": GLSA_DIR %s doesn't exist. Please fix this.\n" % glsaconfig["GLSA_DIR"])
  123.     sys.exit(1)
  124.  
  125. # build glsa lists
  126. completelist = get_glsa_list(glsaconfig["GLSA_DIR"], glsaconfig)
  127.  
  128. if os.access(glsaconfig["CHECKFILE"], os.R_OK):
  129.     checklist = [line.strip() for line in open(glsaconfig["CHECKFILE"], "r").readlines()]
  130. else:
  131.     checklist = []
  132. todolist = [e for e in completelist if e not in checklist]
  133.  
  134. glsalist = []
  135. if "new" in params:
  136.     glsalist = todolist
  137.     params.remove("new")
  138. if "all" in params:
  139.     glsalist = completelist
  140.     params.remove("all")
  141. if "affected" in params:
  142.     # maybe this should be todolist instead
  143.     for x in completelist:
  144.         try:
  145.             myglsa = Glsa(x, glsaconfig)
  146.         except (GlsaTypeException, GlsaFormatException), e:
  147.             if verbose:
  148.                 sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (x, e)))
  149.             continue
  150.         if myglsa.isVulnerable():
  151.             glsalist.append(x)
  152.     params.remove("affected")
  153.  
  154. # remove invalid parameters
  155. for p in params[:]:
  156.     if not (p in completelist or os.path.exists(p)):
  157.         sys.stderr.write(("(removing %s from parameter list as it isn't a valid GLSA specification)\n" % p))
  158.         params.remove(p)
  159.  
  160. glsalist.extend([g for g in params if g not in glsalist])
  161.  
  162. # list short information for given or new GLSA
  163. if mode == "list":
  164.     sys.stderr.write(white("[A]")+" means this GLSA was already applied,\n")
  165.     sys.stderr.write(green("[U]")+" means the system is not affected and\n")
  166.     sys.stderr.write(red("[N]")+" indicates that the system might be affected.\n\n")
  167.  
  168.     for myid in glsalist:
  169.         try:
  170.             myglsa = Glsa(myid, glsaconfig)
  171.         except (GlsaTypeException, GlsaFormatException), e:
  172.             if verbose:
  173.                 sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e)))
  174.             continue
  175.         if myglsa.isApplied():
  176.             status = "[A]"
  177.             color = white
  178.         elif myglsa.isVulnerable():
  179.             status = "[N]"
  180.             color = red
  181.         else:
  182.             status = "[U]"
  183.             color = green
  184.         sys.stdout.write(color(myglsa.nr) + " " + color(status) + " " + myglsa.title + " (") 
  185.         for pkg in myglsa.packages.keys()[:3]:
  186.             sys.stdout.write(" " + pkg + " ")
  187.         if len(myglsa.packages) > 3:
  188.             sys.stdout.write("... ")
  189.         sys.stdout.write(")")
  190.         if list_cve:
  191.             sys.stdout.write(" "+(",".join([r[:13] for r in myglsa.references if r[:4] == "CAN-"])))
  192.         sys.stdout.write("\n")        
  193.     sys.exit(0)
  194.  
  195. # dump, fix, inject and fix are nearly the same code, only the glsa method call differs
  196. if mode in ["dump", "fix", "inject", "pretend"]:
  197.     for myid in glsalist:
  198.         try:
  199.             myglsa = Glsa(myid, glsaconfig)
  200.         except (GlsaTypeException, GlsaFormatException), e:
  201.             if verbose:
  202.                 sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e)))
  203.             continue
  204.         if mode == "dump":
  205.             myglsa.dump()
  206.         elif mode == "fix":
  207.             sys.stdout.write("fixing "+myid+"\n")
  208.             mergelist = myglsa.getMergeList()
  209.             for pkg in mergelist:
  210.                 sys.stdout.write(">>> merging "+pkg+"\n")
  211.                 # using emerge for the actual merging as it contains the dependency
  212.                 # code and we want to be consistent in behaviour. Also this functionality
  213.                 # will be integrated in emerge later, so it shouldn't hurt much.
  214.                 emergecmd = "emerge --oneshot " + glsaconfig["EMERGE_OPTS"] + " =" + pkg
  215.                 if verbose:
  216.                     sys.stderr.write(emergecmd+"\n")
  217.                 exitcode = os.system(emergecmd)
  218.                 if exitcode:
  219.                     sys.exit(exitcode)
  220.             myglsa.inject()
  221.         elif mode == "pretend":
  222.             sys.stdout.write("Checking GLSA "+myid+"\n")
  223.             mergelist = myglsa.getMergeList()
  224.             if mergelist:
  225.                 sys.stdout.write("The following updates will be performed for this GLSA:\n")
  226.                 for pkg in mergelist:
  227.                     # we simplify a bit here
  228.                     oldver = portage.db["/"]["vartree"].dbapi.match(portage.dep_getkey(pkg))[-1]
  229.                     oldver = oldver[len(portage.dep_getkey(oldver))+1:]
  230.                     sys.stdout.write("     " + pkg + " (" + oldver + ")\n")
  231.             else:
  232.                 sys.stdout.write("Nothing to do for this GLSA\n")
  233.         elif mode == "inject":
  234.             sys.stdout.write("injecting " + myid + "\n")
  235.             myglsa.inject()
  236.         sys.stdout.write("\n")
  237.     sys.exit(0)
  238.  
  239. # test is a bit different as Glsa.test() produces no output
  240. if mode == "test":
  241.     outputlist = []
  242.     for myid in glsalist:
  243.         try:
  244.             myglsa = Glsa(myid, glsaconfig)
  245.         except (GlsaTypeException, GlsaFormatException), e:
  246.             if verbose:
  247.                 sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e)))
  248.             continue
  249.         if myglsa.isVulnerable():
  250.             outputlist.append(myglsa.nr)
  251.     if len(outputlist) > 0:
  252.         sys.stderr.write("This system is affected by the following GLSAs:\n")
  253.         for g in outputlist:
  254.             sys.stdout.write(g)
  255.             if verbose:
  256.                 sys.stdout.write(" ( " + myglsa.title + " )\n")
  257.             else:
  258.                 sys.stdout.write("\n")
  259.     else:
  260.         sys.stderr.write("This system is not affected by any of the listed GLSAs\n")
  261.     sys.exit(0)
  262.     
  263. # something wrong here, all valid paths are covered with sys.exit()
  264. sys.stderr.write("nothing more to do\n")
  265. sys.exit(2)
  266.